package com.crayfish.banner.widget.calendar2;

import java.text.SimpleDateFormat;
import java.util.Calendar;

import android.animation.Animator;
import android.animation.ObjectAnimator;
import android.annotation.SuppressLint;
import android.content.Context;
import android.util.AttributeSet;
import android.util.Log;
import android.view.GestureDetector;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewTreeObserver;
import android.widget.FrameLayout;
import android.widget.LinearLayout;
import android.widget.ListView;

import com.crayfish.banner.R;

/**
 * Created by lin on 2016/8/23.
 */
public class CalendarListView extends FrameLayout {

    private static final String TAG = "CalendarListView";
    private ListView pullToRefreshListView;
    private CalendarView calendarView;
    private WeekDayView weekDayView;

    private CalendarStatus calendarStatus = CalendarStatus.MONTH;
    private Status status = Status.IDLE;
    private GestureDetector gestureDetector;
    private ObjectAnimator objectAnimator3;
    private ObjectAnimator objectAnimator4;

    public CalendarListView(Context context, AttributeSet attrs) {
        super(context, attrs);
        gestureDetector = new GestureDetector(context, new FlingListener());
        LayoutInflater.from(context).inflate(R.layout.layout_calendar_listview,
                this);
        calendarView = (CalendarView) this.findViewById(R.id.calendarView);
        weekDayView = (WeekDayView) this.findViewById(R.id.weekDayView);
        pullToRefreshListView = (ListView) this
                .findViewById(R.id.listView);
        initListener();
    }

    private DateClick dateClick = null;

    /**
     * 点击日期回调事件
     */
    public interface DateClick {
        void onDateClick(int year, int month, int day);
    }

    /**
     * API 设置日期点击事件
     *
     * @param dateClick
     */
    public void setOnDateClick(DateClick dateClick) {
        this.dateClick = dateClick;
    }

    private SwitchMonthClick switchMonthClick = null;

    /**
     * 点击月份切换回调事件
     */
    public interface SwitchMonthClick {
        void onSwitchMonthClick(int year, int month, int day);
    }

    /**
     * API 月份切换事件
     *
     * @param switchMonthClick
     */
    public void setOnSwitchMonthClick(SwitchMonthClick switchMonthClick) {
        this.switchMonthClick = switchMonthClick;
    }

    private StateWeekOrMonthListener stateWeekOrMonthListener = null;

    /**
     * 点击月份切换回调事件
     */
    public interface StateWeekOrMonthListener {
        void onStateWeekOrMonthClick(int state);
    }

    /**
     * API 月份切换事件
     */
    public void setOnStateWeekOrMonthListener(
            StateWeekOrMonthListener stateWeekOrMonthListener) {
        this.stateWeekOrMonthListener = stateWeekOrMonthListener;
    }

    public int getYear() {
        return calendarView.getmSelYear();
    }

    public int getMonth() {
        return calendarView.getmSelMonth();
    }

    public int getDay() {
        return calendarView.getmSelDay();
    }

    public String getYearMonthDay() {
        Calendar calendar = Calendar.getInstance();
        calendar.set(calendarView.getmSelYear(), calendarView.getmSelMonth(),
                calendarView.getmSelDay());
        return new SimpleDateFormat("yyyy-MM-dd").format(calendar.getTime());
    }

    /**
     * API 跳转至今天
     */
    public void setTodayToView() {
        calendarView.setTodayToView();
        weekDayView.setTodayToView();
        switchMonthClick.onSwitchMonthClick(calendarView.getmSelYear(),
                calendarView.getmSelMonth(), calendarView.getmSelDay());
    }

    /**
     * API 跳转至某天
     */
    public void setToDateToView(int year, int month, int day) {
        calendarView.setToDateToView(year, month, day);
        weekDayView.setToDateToView(year, month, day);
    }

//    public PullToRefreshListView getPullToRefreshListView() {
//        return pullToRefreshListView;
//    }

    protected void initListener() {
        calendarView.getViewTreeObserver().addOnGlobalLayoutListener(
                new ViewTreeObserver.OnGlobalLayoutListener() {
                    @Override
                    public void onGlobalLayout() {
                        int listViewHeight = CalendarListView.this.getHeight()
                                - weekDayView.getHeight();
                        LinearLayout.LayoutParams layoutParams = (LinearLayout.LayoutParams) pullToRefreshListView
                                .getLayoutParams();
                        layoutParams.height = listViewHeight;
                        pullToRefreshListView.setLayoutParams(layoutParams);
                    }
                });
        calendarView.setOnLastOrNextMonthListener(
                new CalendarView.onLastOrNextMonthListener() {

                    @Override
                    public void onLastOrNextMonth(int tag) {
                        // TODO Auto-generated method stub
                        if (tag == 0) {
                            calendarView.onNextMonth();
                            weekDayView.onNextMonth();
                            switchMonthClick.onSwitchMonthClick(
                                    calendarView.getmSelYear(),
                                    calendarView.getmSelMonth(),
                                    calendarView.getmSelDay());
                        } else if (tag == 1) {
                            calendarView.onLastMonth();
                            weekDayView.onLastMonth();
                            switchMonthClick.onSwitchMonthClick(
                                    calendarView.getmSelYear(),
                                    calendarView.getmSelMonth(),
                                    calendarView.getmSelDay());
                        }
                    }
                });
        calendarView.setOnDateClick(new CalendarView.DateClick() {
            @Override
            public void onDateClick(int year, int month, int day) {
                weekDayView.setDay(year, month, day);
                if (dateClick != null) {
                    dateClick.onDateClick(year, month, day);
                }
            }
        });
        weekDayView.setOnDateClick(new WeekDayView.DateClick() {
            @Override
            public void onDateClick(int year, int month, int day) {
                calendarView.setDay(year, month, day);
                if (dateClick != null) {
                    dateClick.onDateClick(year, month, day);
                }
            }
        });
    }

    public void setTagDays(String[] tagDays) {
        calendarView.setTagDays(tagDays);
        weekDayView.setTagDays(tagDays);
    }

    private int downY, downX, startY;

    @SuppressLint("NewApi")
    @Override
    public boolean dispatchTouchEvent(MotionEvent ev) {
        CalendarView.SelectedRowColumn selectedRowColumn = calendarView
                .getSelectedRowColumn();
        switch (ev.getAction()) {
            case MotionEvent.ACTION_DOWN:
                downY = (int) ev.getRawY();
                downX = (int) ev.getRawX();
                startY = (int) ev.getRawY();
                status = Status.IDLE;
                break;
            case MotionEvent.ACTION_MOVE:
                int curY = (int) ev.getRawY();
                int curX = (int) ev.getRawX();
                if (calendarStatus == CalendarStatus.MONTH && curY > downY) {// 月视图下滑
                    return super.dispatchTouchEvent(ev);
                }
                if (calendarStatus == CalendarStatus.WEEK && curY < downY) {// 周视图上滑
                    return super.dispatchTouchEvent(ev);
                }
                if (calendarStatus == CalendarStatus.WEEK
                        && pullToRefreshListView
                        .getFirstVisiblePosition() != 0 && curY > downY) {
                    return super.dispatchTouchEvent(ev);
                }
                if (Math.abs(curX - downX) > Math.abs(curY - downY)
                        && calendarStatus == CalendarStatus.MONTH) {
                    Log.d(TAG,
                            "当前滑动状态" + status.toString()
                                    +"当前日历状态"+ calendarStatus.toString());
                    status = Status.HORIZONTAL;
                }
                if (Math.abs(curX - downX) < Math.abs(curY - downY)&&Math.abs(curY - downY)>10) {
                    status = Status.DRAGGING;
                }
                gestureDetector.onTouchEvent(ev);

                break;
            case MotionEvent.ACTION_UP:
            case MotionEvent.ACTION_CANCEL:
                Log.d(TAG, "status状态" + status.toString());
                gestureDetector.onTouchEvent(ev);
                break;
        }
        return super.dispatchTouchEvent(ev);
    }

    @Override
    public boolean onInterceptTouchEvent(MotionEvent ev) {
        // TODO Auto-generated method stub
        if(status == Status.DRAGGING){
            return true;
        }
        return super.onInterceptTouchEvent(ev);
    }

    @SuppressLint("ClickableViewAccessibility") @Override
    public boolean onTouchEvent(MotionEvent ev) {
        // TODO Auto-generated method stub
        CalendarView.SelectedRowColumn selectedRowColumn = calendarView
                .getSelectedRowColumn();
        switch (ev.getAction()) {
            case MotionEvent.ACTION_DOWN:
                downY = (int) ev.getRawY();
                downX = (int) ev.getRawX();
                startY = (int) ev.getRawY();
                status = Status.IDLE;
                return super.onTouchEvent(ev);
            case MotionEvent.ACTION_MOVE:
                int curY = (int) ev.getRawY();
                int curX = (int) ev.getRawX();

                if (Math.abs(calendarView.getTranslationY()) >= ((selectedRowColumn.row) * weekDayView
                        .getHeight()) && curY < startY) {
                    post(new Runnable() {
                        @Override
                        public void run() {
                            weekDayView.setVisibility(VISIBLE);
                        }
                    });
                }
                // +10防止weekDayView过早出现
                if (Math.abs(calendarView.getTranslationY() + 10) <= ((selectedRowColumn.row) * weekDayView
                        .getHeight()) && curY > startY) {
                    post(new Runnable() {
                        @Override
                        public void run() {
                            weekDayView.setVisibility(GONE);
                        }
                    });
                }
                if (Math.abs(calendarView.getTranslationY()) >= 0
                        && Math.abs(calendarView.getTranslationY()) <= 50) {
                    calendarStatus = CalendarStatus.MONTH;
                }
                if (Math.abs(calendarView.getTranslationY()) >= (calendarView
                        .getHeight() - weekDayView.getHeight()) && curY < startY) {
                    pullToRefreshListView.setTranslationY(-(calendarView
                            .getHeight() - weekDayView.getHeight()));
                    calendarView
                            .setTranslationY(-(calendarView.getHeight() - weekDayView
                                    .getHeight()));
                }
                if (curY > startY && pullToRefreshListView.getTranslationY() >= 0) {
                    pullToRefreshListView.setTranslationY(0);
                }
                pullToRefreshListView
                        .setTranslationY(calendarView.getTranslationY()
                                + (curY - startY)
                                / ((calendarView.getHeight() / weekDayView
                                .getHeight()) - 3));
                calendarView
                        .setTranslationY(calendarView.getTranslationY()
                                + (curY - startY)
                                / ((calendarView.getHeight() / weekDayView
                                .getHeight()) - 3));

                startY = curY;
                if(calendarView.getTranslationY()>0){
                    calendarView.setTranslationY(0);
                }
                status = Status.DRAGGING;
                return super.onTouchEvent(ev);
            case MotionEvent.ACTION_UP:
            case MotionEvent.ACTION_CANCEL:
                curY = (int) ev.getRawY();
                curX = (int) ev.getRawX();
                Log.d(TAG, "status状态" + status.toString());
                if (status == Status.ANIMATING) {
                    return super.onTouchEvent(ev);
                }
                if (downY - curY > 10) {
                    if (Math.abs((curY - downY)) > calendarView.getHeight() / 2.0f) {
                        animationToTop(selectedRowColumn);
                    } else {
                        animationToBottom(selectedRowColumn);
                    }
                } else if (downY - curY < -10) {
                    if (Math.abs((curY - downY)) > calendarView.getHeight() / 2.0f) {
                        animationToBottom(selectedRowColumn);
                    } else {
                        animationToTop(selectedRowColumn);
                    }
                }
                return super.onTouchEvent(ev);
            default:
                return super.onTouchEvent(ev);
        }
    }

    private class FlingListener extends GestureDetector.SimpleOnGestureListener {
        @Override
        public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,
                               float velocityY) {
            if (status != Status.ANIMATING) {
                if (Math.abs(velocityY) > Math.abs(velocityX)) {
                    Log.d(TAG, "手势上下滑动");
                    if (velocityY < -100) {
                        animationToTop(calendarView.getSelectedRowColumn());
                    } else if (velocityY > 100) {
                        animationToBottom(calendarView.getSelectedRowColumn());
                    }
                }
                // else {
                // Log.d(TAG, "手势左右滑动");
                // if (velocityX < -0
                // && calendarStatus == CalendarStatus.MONTH) {
                // calendarView.onNextMonth();
                // weekDayView.onNextMonth();
                // switchMonthClick.onSwitchMonthClick(
                // calendarView.getmSelYear(),
                // calendarView.getmSelMonth(),
                // calendarView.getmSelDay());
                // } else if (velocityX > 0
                // && calendarStatus == CalendarStatus.MONTH) {
                // calendarView.onLastMonth();
                // weekDayView.onLastMonth();
                // switchMonthClick.onSwitchMonthClick(
                // calendarView.getmSelYear(),
                // calendarView.getmSelMonth(),
                // calendarView.getmSelDay());
                // }
                // }
            }
            return super.onFling(e1, e2, velocityX, velocityY);
        }

        @Override
        public boolean onScroll(MotionEvent e1, MotionEvent e2,
                                float distanceX, float distanceY) {
            return super.onScroll(e1, e2, distanceX, distanceY);
        }
    }

    /**
     * 月视图切换到周视图
     *
     * @param selectedRowColumn
     */
    @SuppressLint("NewApi")
    private void animationToTop(CalendarView.SelectedRowColumn selectedRowColumn) {
        status = Status.ANIMATING;
        ObjectAnimator objectAnimator1 = ObjectAnimator.ofFloat(this,
                "translationY",
                -(weekDayView.getHeight() * selectedRowColumn.row));
        objectAnimator1.setTarget(pullToRefreshListView);

        final double rate = weekDayView.getHeight()
                * (selectedRowColumn.row + 1)
                / (calendarView.getHeight() * 1.01f);
        ObjectAnimator objectAnimator2 = ObjectAnimator.ofFloat(this,
                "translationY",
                -(weekDayView.getHeight() * selectedRowColumn.row));
        objectAnimator2.setTarget(calendarView);

        objectAnimator3 = null;
        objectAnimator3 = ObjectAnimator.ofFloat(this, "translationY",
                -(calendarView.getHeight() - weekDayView.getHeight()));
        objectAnimator3.setTarget(calendarView);

        objectAnimator4 = null;
        objectAnimator4 = ObjectAnimator.ofFloat(this, "translationY",
                -(calendarView.getHeight() - weekDayView.getHeight()));
        objectAnimator4.setTarget(pullToRefreshListView);
        if (weekDayView.getVisibility() == VISIBLE) {
            objectAnimator3.setDuration((int) (300 * rate)).start();
            objectAnimator4.setDuration((int) (300 * rate)).start();
        } else {
            objectAnimator1.setDuration((int) (300 * rate)).start();
            objectAnimator2.setDuration((int) (300 * rate)).start();
        }

        objectAnimator2.addListener(new Animator.AnimatorListener() {
            @Override
            public void onAnimationStart(Animator animation) {

            }

            @Override
            public void onAnimationEnd(Animator animation) {
                objectAnimator3.setDuration((int) (300 * rate)).start();
                objectAnimator4.setDuration((int) (300 * rate)).start();
                weekDayView.setVisibility(VISIBLE);
            }

            @Override
            public void onAnimationCancel(Animator animation) {

            }

            @Override
            public void onAnimationRepeat(Animator animation) {

            }
        });
        objectAnimator3.addListener(new Animator.AnimatorListener() {
            @Override
            public void onAnimationStart(Animator animation) {

            }

            @Override
            public void onAnimationEnd(Animator animation) {
                calendarStatus = CalendarStatus.WEEK;
                status = Status.IDLE;
                stateWeekOrMonthListener.onStateWeekOrMonthClick(View.VISIBLE);
                Log.d(TAG, "calendarStatus:" + calendarStatus.toString());
            }

            @Override
            public void onAnimationCancel(Animator animation) {

            }

            @Override
            public void onAnimationRepeat(Animator animation) {

            }
        });
    }

    /**
     * 周视图切换到月视图
     *
     * @param selectedRowColumn
     */
    @SuppressLint("NewApi")
    private void animationToBottom(
            CalendarView.SelectedRowColumn selectedRowColumn) {
        status = Status.ANIMATING;
        ObjectAnimator objectAnimator1 = ObjectAnimator.ofFloat(this,
                "translationY", -weekDayView.getHeight()
                        * selectedRowColumn.row);
        objectAnimator1.setTarget(pullToRefreshListView);

        final double rate = weekDayView.getHeight()
                * (selectedRowColumn.row + 1)
                / (calendarView.getHeight() * 1.0f);
        ObjectAnimator objectAnimator2 = ObjectAnimator.ofFloat(this,
                "translationY", -weekDayView.getHeight()
                        * selectedRowColumn.row);
        objectAnimator2.setTarget(calendarView);

        objectAnimator3 = null;
        objectAnimator3 = ObjectAnimator.ofFloat(this, "translationY", 0);
        objectAnimator3.setTarget(calendarView);

        objectAnimator4 = null;
        objectAnimator4 = ObjectAnimator.ofFloat(this, "translationY", 0);
        objectAnimator4.setTarget(pullToRefreshListView);

        if (weekDayView.getVisibility() == GONE) {
            objectAnimator3.setDuration((int) (300 * rate)).start();
            objectAnimator4.setDuration((int) (300 * rate)).start();
        } else {
            objectAnimator1.setDuration((int) (300 * rate)).start();
            objectAnimator2.setDuration((int) (300 * rate)).start();
        }
        objectAnimator2.addListener(new Animator.AnimatorListener() {
            @Override
            public void onAnimationStart(Animator animation) {

            }

            @Override
            public void onAnimationEnd(Animator animation) {
                objectAnimator3.setDuration((int) (300 * rate)).start();
                objectAnimator4.setDuration((int) (300 * rate)).start();
                weekDayView.setVisibility(GONE);
            }

            @Override
            public void onAnimationCancel(Animator animation) {

            }

            @Override
            public void onAnimationRepeat(Animator animation) {

            }
        });
        objectAnimator3.addListener(new Animator.AnimatorListener() {
            @Override
            public void onAnimationStart(Animator animation) {

            }

            @Override
            public void onAnimationEnd(Animator animation) {
                calendarStatus = CalendarStatus.MONTH;
                status = Status.IDLE;
                stateWeekOrMonthListener.onStateWeekOrMonthClick(View.GONE);
                Log.d(TAG, "calendarStatus:" + calendarStatus.toString());
            }

            @Override
            public void onAnimationCancel(Animator animation) {

            }

            @Override
            public void onAnimationRepeat(Animator animation) {

            }
        });
    }

    public enum CalendarStatus {
        MONTH, // 月视图状态
        WEEK// 周视图状态
    }

    public enum Status {
        IDLE, // 常态
        HORIZONTAL,//水平滑动
        DRAGGING, // 拖动状态
        ANIMATING// 动画状态
    }
}

